package cn.rxls.community.service.impl;

import cn.rxls.community.enums.ResultEnum;
import cn.rxls.community.exception.BusinessException;
import cn.rxls.community.service.UploadFileService;
import cn.rxls.community.util.HttpUtil;
import cn.rxls.community.util.StrFileUtil;
import cn.rxls.community.util.WhitelistFiltering;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 文件上传服务
 */
@Service("uploadFileService")
@Transactional(rollbackFor = Exception.class)
public class UploadFileServiceImpl implements UploadFileService {

    /**
     * 配置文件中配置文件保存的路径
     */
    @Value("${img.location}")
    private String folder;

    /**
     * 单个图片上传大小
     */
    @Value("${img.size}")
    private Integer fileSize;

    /**
     * 图片白名单检查
     */
    @Resource
    private WhitelistFiltering whitelistFiltering;

    /**
     * 图片上传
     *
     * @param files 上传的文件列表
     * @return 多条上传的图片路径信息
     */
    @Override
    public List<String> uploadImage(MultipartFile[] files) {
        HttpServletRequest request = HttpUtil.getHttpInfo();

        //获取用户信息，判定是否合法
        Map<String, Object> userLoginInfo = HttpUtil.getUserLoginInfo();
        Optional.ofNullable(userLoginInfo).orElseThrow(() -> new BusinessException(ResultEnum.ERROR_LOGIN));

        //如果上传文件为空
        Optional.ofNullable(files).orElseThrow(() -> new BusinessException(ResultEnum.ERROR));

        //检查所有的上传文件类型是否是一个图片，并且大小是否合适
        Arrays.stream(files).forEach(f -> {
            //获取文件名
            String originalFilename = f.getOriginalFilename();
            //为空标识文件错误
            Optional.ofNullable(originalFilename).orElseThrow(() -> new BusinessException(ResultEnum.ERROR_UPLOAD_IMG_TYPE));
            //获取文件后缀名
            String intercept = StrFileUtil.intercept(originalFilename, '.');
            whitelistFiltering.file(intercept);

            //获取文件大小
            long fileSizeInBytes = f.getSize();
            long fileSizeInMegabytes = fileSizeInBytes / (1024 * 1024); // 转换为MB
            //文件超出限制
            if (fileSizeInMegabytes > fileSize) {
                throw new BusinessException(ResultEnum.ERROR_UPLOAD_IMG_SIZE);
            }
        });

        //返回的图片路径集合
        List<String> urlList = new ArrayList<>();
        //存储图片
        Arrays.stream(files).forEach(f -> {
            //文件后缀名称
            String intercept = StrFileUtil.intercept(Objects.requireNonNull(f.getOriginalFilename()), '.');
            //最终图片存储的名称
            String fileUrl = "image" + UUID.randomUUID() + intercept;
            //写入本地
            try {
                f.transferTo(new File(folder + fileUrl));
                //项目的端口号http://localhost:8942
                String basePath = request.getScheme()//获取协议号
                        + "://"
                        + request.getServerName()//获取IP地址
                        + ":"
                        + request.getServerPort()//获取端口号
                        + request.getContextPath();//获取工程路径
                //图片访问路径,用户id一起拼接
                String url = basePath + "/upload/" + fileUrl;

                urlList.add(url);
            } catch (IOException e) {
                throw new BusinessException(ResultEnum.ERROR, e);
            }
        });
        return urlList;
    }


    /**
     * 删除图片
     *
     * @param path 文件名
     * @return 成功数
     */
    @Override
    public Integer delImage(List<String> path) {

        //判定是否是管理员

        //删除成功数
        AtomicInteger size = new AtomicInteger();
        //前端页面处理路径，
        path.forEach(p -> {
            int lastIndexOf = p.lastIndexOf("/");
            String img_path = p.substring(lastIndexOf + 1);
            img_path = "D:/upload/" + img_path;
            File file = new File(img_path);
            if (file.exists()) {//文件是否存在
                if (file.delete()) {//存在就删了，返回1
                    size.addAndGet(1);
                }
            }
        });
        return size.get();
    }


}
